<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>Plugin: styles</title>
	<link rel="stylesheet" type="text/css" href="../../test.css" />
	<script type="text/javascript" src="../../../ckeditor.js"></script>
	<script type="text/javascript" src="../../test.js"></script>
	<script type="text/javascript">

CKEDITOR.plugins.load( [ 'styles', 'domiterator', 'htmldataprocessor' ] );

	</script>
	<script type="text/javascript">
	//<![CDATA[

var testCase;

CKEDITOR.test.addTestCase( testCase = (function()
{
	// Local references.
	var assert			= CKEDITOR.test.assert;
	var getInnerHtml	= CKEDITOR.test.getInnerHtml;

	function getInnerHtmlParsed( element )
	{
		var dataProcessor = new CKEDITOR.htmlDataProcessor();
		dataProcessor.writer = new CKEDITOR.htmlParser.basicWriter();
		return dataProcessor.toDataFormat( getInnerHtml( element, false ) );
	}

	var doc = new CKEDITOR.dom.document( document );

	return {
		test_inline1 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this is some sample text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ).getFirst(), 5 );
			range.setEnd( doc.getById( '_P1' ).getFirst(), 7 );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.applyToRange( range );

			assert.areSame( 'this <b>is</b> some sample text', getInnerHtml( '_P1' ) );
		},

		test_inline2 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <b>is some </b>sample text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ).getChild( 1 ), 0 );
			range.setEnd( doc.getById( '_P1' ), 2 );

			var style = new CKEDITOR.style( { element : 'i' } );
			style.applyToRange( range );

			assert.areSame( 'this <i><b>is some </b></i>sample text', getInnerHtml( '_P1' ) );
		},

		test_inline3 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <b>is some </b>sample text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ).getChild( 1 ), 0 );
			range.setEnd( doc.getById( '_P1' ).getChild( 1 ).getFirst(), 2 );

			var style = new CKEDITOR.style( { element : 'i' } );
			style.applyToRange( range );

			assert.areSame( 'this <b><i>is</i> some </b>sample text', getInnerHtml( '_P1' ) );
		},

		// Inline - Remove inner duplicates.
		test_inline4 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <b>is some </b>sample text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 0 );
			range.setEnd( doc.getById( '_P1' ), 3 );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.applyToRange( range );

			assert.areSame( '<b>this is some sample text</b>', getInnerHtml( '_P1' ) );
		},

		// Inline - Merge with next.
		test_inline5 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <b>is some </b>sample text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 0 );
			range.setEnd( doc.getById( '_P1' ), 1 );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.applyToRange( range );

			assert.areSame( '<b>this is some </b>sample text', getInnerHtml( '_P1' ) );
		},

		// Inline - Merge with previous.
		test_inline6 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <b>is some </b>sample text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 2 );
			range.setEnd( doc.getById( '_P1' ).getChild( 2 ), 6 );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.applyToRange( range );

			assert.areSame( 'this <b>is some sample</b> text', getInnerHtml( '_P1' ) );
		},

		// Inline - Merge several with next.
		test_inline7 : function()
		{
			doc.getById( '_P1' ).setHtml( '<i><u>this </u></i><b><i><u>is</u> some</i> sample</b> text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 0 );
			range.setEnd( doc.getById( '_P1' ), 1 );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.applyToRange( range );

			assert.areSame( '<b><i><u>this is</u> some</i> sample</b> text', getInnerHtml( '_P1' ) );
		},

		// Inline - Merge several with previous.
		test_inline8 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <b>is <i>some <u>sample</u></i></b><i><u> text</u></i>' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 2 );
			range.setEnd( doc.getById( '_P1' ), 3 );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.applyToRange( range );

			assert.areSame( 'this <b>is <i>some <u>sample text</u></i></b>', getInnerHtml( '_P1' ) );
		},

		test_inline9 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <i>is some </i>sample text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 0 );
			range.setEnd( doc.getById( '_P1' ).getChild( 1 ), 0 );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.applyToRange( range );

			assert.areSame( '<b>this </b><i>is some </i>sample text', getInnerHtml( '_P1' ) );
		},

		test_inline10 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this is some sample text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 0 );
			range.setEnd( doc.getById( '_P1' ), 1 );

			var style = new CKEDITOR.style(
				{
					element : 'b',
					attributes :
						{
							lang : 'it',
							title : 'test'
						},
					styles :
						{
							'font-size' : '10pt',
							'text-decoration' : 'line-through'
						}
				} );
			style.applyToRange( range );

			assert.areSame( '<b lang="it" style="font-size:10pt;text-decoration:line-through;" title="test">this is some sample text</b>', getInnerHtml( '_P1' ) );
		},

		test_inline11 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <b lang="it" class="sample">is</b> <b lang="it" style="font-size: 10pt; text-decoration: line-through;" title="test">some sample</b> <b>t</b>ext' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 0 );
			range.setEnd( doc.getById( '_P1' ), 7 );

			var style = new CKEDITOR.style(
				{
					element : 'b',
					attributes :
						{
							lang : 'it',
							title : 'test'
						},
					styles :
						{
							'font-size' : '10pt',
							'text-decoration' : 'line-through'
						}
				} );
			style.applyToRange( range );

			assert.areSame( '<b lang="it" style="font-size: 10pt; text-decoration: line-through;" title="test">this <b class="sample">is</b> some sample text</b>', getInnerHtml( '_P1' ) );
		},

		test_inline11 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <span class="a">is</span> some <span class="b">sample</span> text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 0 );
			range.setEnd( doc.getById( '_P1' ), 5 );

			var style = new CKEDITOR.style( { element : 'span', attributes : { 'class' : 'b' } } );
			style.applyToRange( range );

			assert.areSame( '<span class="b">this <span class="a">is</span> some sample text</span>', getInnerHtml( '_P1' ) );
		},

		test_inline12 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <span style="font-size:12pt; font-weight:600">is</span> some <span style="font-size:10px;">sample</span> text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 0 );
			range.setEnd( doc.getById( '_P1' ), 5 );

			var style = new CKEDITOR.style( { element : 'span', styles : { 'font-size' : '1.5em' } } );
			style.applyToRange( range );

			assert.areSame( '<span style="font-size:1.5em;">this <span style="font-weight:600;">is</span> some sample text</span>', getInnerHtml( '_P1' ) );
		},

		test_inline13 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this <b>is some sample</b> text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ).getChild( 1 ).getFirst(), 3 );
			range.setEnd( doc.getById( '_P1' ), 3 );

			var style = new CKEDITOR.style( { element : 'i' } );
			style.applyToRange( range );

			assert.areSame( 'this <b>is <i>some sample</i></b><i> text</i>', getInnerHtml( '_P1' ) );
		},

		test_inline14 : function()
		{
			var para = doc.getById( '_P1' );

			para.setHtml( 'this is some sample text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( para.getFirst(), 0 );
			range.setEnd( para.getFirst(), 7 );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.applyToRange( range );

			assert.areSame( '<b>this is</b> some sample text', getInnerHtml( '_P1' ), 'First range' );

			para.setHtml( para.getHtml() );

			range = new CKEDITOR.dom.range( doc );
			range.setStart( para.getFirst().getFirst(), 5 );
			range.setEnd( para.getChild( 1 ), 5 );

			style.applyToRange( range );

			assert.areSame( '<b>this is some</b> sample text', getInnerHtml( '_P1' ), 'Second range' );
		},

		test_inline15 : function()
		{
			var para = doc.getById( '_P1' );

			para.setHtml( 'this is some sample text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( para.getFirst(), 0 );
			range.setEnd( para.getFirst(), 7 );

			var style = new CKEDITOR.style( { element : 'span', styles : { 'font-family' : '#(family)' } }, { family : 'Arial,Helvetica,sans-serif' } );
			style.applyToRange( range );

			assert.areSame( '<span style="font-family:arial,helvetica,sans-serif;">this is</span> some sample text', getInnerHtml( '_P1' ), 'First range' );

			para.setHtml( para.getHtml() );

			range = new CKEDITOR.dom.range( doc );
			range.setStart( para.getFirst().getFirst(), 5 );
			range.setEnd( para.getChild( 1 ), 5 );

			style = new CKEDITOR.style( { element : 'span', styles : { 'font-family' : '#(family)' } }, { family : 'Georgia,serif' } );
			style.applyToRange( range );

			assert.areSame( '<span style="font-family:arial,helvetica,sans-serif;">this <span style="font-family:georgia,serif;">is</span></span><span style="font-family:georgia,serif;"> some</span> sample text', getInnerHtml( '_P1' ), 'Second range' );
		},

		test_inline16 : function()
		{
			var para = doc.getById( '_P1' );

			para.setHtml( '<b lang="pt" style="font-size:11pt;color:red;">this is some sample text</b>' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( para.getFirst().getFirst(), 4 );
			range.setEnd( para.getFirst(), 10 );

			var style = new CKEDITOR.style( { element : 'b', styles : { color : 'red', 'font-weight' : '700' } } );
			style.applyToRange( range );

			assert.areSame( '<b lang="pt" style="color:red;font-size:11pt;">this<b style="font-weight:700;"> is some sample text</b></b>', getInnerHtml( '_P1' ), 'First range' );
		},

		test_inline_nobreak1 : function()
		{
			doc.getById( '_P1' ).setHtml( 'this is <a href="http://example.com/">some sample</a> text' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 0 );
			range.setEnd( doc.getById( '_P1' ).getChild( 1 ).getFirst(), 4 );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.applyToRange( range );

			assert.areSame( '<b>this is </b><a href="http://example.com/"><b>some</b> sample</a> text', getInnerHtml( '_P1' ) );
		},

		test_ticket_2040 : function()
		{
			doc.getById( '_P1' ).setHtml( 'This is some <strong>sample text<\/strong>. You are using <a href="http://www.fckeditor.net/">ckeditor<\/a>.' );

			var range = new CKEDITOR.dom.range( doc );
			range.setStart( doc.getById( '_P1' ), 1 );
			range.setEnd( doc.getById( '_P1' ).getChild( 1 ).getFirst(), 6 );

			var style = new CKEDITOR.style( { element : 'i' } );
			style.applyToRange( range );

			assert.areSame( 'this is some <strong><i>sample</i> text<\/strong>. you are using <a href="http://www.fckeditor.net/">ckeditor<\/a>.', getInnerHtml( '_P1' ) );
		},

		test_checkElementRemovable1 : function()
		{
			var element = CKEDITOR.dom.element.createFromHtml( '<b>Test</b>', doc );

			var style = new CKEDITOR.style( { element : 'b' } );

			assert.isTrue( style.checkElementRemovable( element ) );
		},

		test_checkElementRemovable2 : function()
		{
			var element = CKEDITOR.dom.element.createFromHtml( '<b>Test</b>', doc );

			var style = new CKEDITOR.style( { element : 'i' } );

			assert.isFalse( style.checkElementRemovable( element ) );
		},

		test_checkElementRemovable3 : function()
		{
			var element = CKEDITOR.dom.element.createFromHtml( '<b>Test</b>', doc );

			var style = new CKEDITOR.style( { element : 'b', attributes : { lang : 'pt' } } );

			assert.isTrue( style.checkElementRemovable( element ) );
		},

		test_checkElementRemovable4 : function()
		{
			var element = CKEDITOR.dom.element.createFromHtml( '<b>Test</b>', doc );

			var style = new CKEDITOR.style( { element : 'b', attributes : { lang : 'pt' } } );

			assert.isFalse( style.checkElementRemovable( element, true ) );
		},

		test_checkElementRemovable5 : function()
		{
			var element = CKEDITOR.dom.element.createFromHtml( '<span lang="pt" style="color : #fff">Test</span>', doc );

			var style = new CKEDITOR.style( { element : 'span', attributes : { lang : 'pt' }, style : { color : '#ffffff' } } );

			assert.isTrue( style.checkElementRemovable( element, true ) );
		},

		test_checkElementRemovable6 : function()
		{
			var element = CKEDITOR.dom.element.createFromHtml( '<span lang="pt" style="color : #fff">Test</span>', doc );

			var style = new CKEDITOR.style( { element : 'span', attributes : { lang : 'pt' }, style : { color : '#fffff0' } } );

			assert.isTrue( style.checkElementRemovable( element, true ) );
		},

		test_checkElementRemovable7 : function()
		{
			var element = CKEDITOR.dom.element.createFromHtml( '<span lang="pt" style="color : #fff">Test</span>', doc );

			var style = new CKEDITOR.style( { element : 'span', attributes : { lang : 'fr' }, style : { color : '#ffffff' } } );

			assert.isFalse( style.checkElementRemovable( element, true ) );
		},

		test_checkElementRemovable8 : function()
		{
			var element = CKEDITOR.dom.element.createFromHtml( '<span lang="pt" style="font-size: 10px">Test</span>', doc );

			var style = new CKEDITOR.style( { element : 'span', attributes : { lang : 'pt' , style : 'font-size:10px;' } } );

			assert.isTrue( style.checkElementRemovable( element, true ) );
		},

		test_ticket_3091 : function()
		{
			var element = doc.getById( '_P1' );
			element.setHtml( 'outter<table><tr><td>text</td></tr></table>outter' );

			var range = new CKEDITOR.dom.range( doc );
			range.selectNodeContents( element );

			var styleDef =
			{
				element		: 'span',
				styles		: { 'font-family' : '#(family)' },
				overrides	: [ { element : 'font', attributes : { 'face' : null } } ]
			};

			var style = new CKEDITOR.style( styleDef, { 'family' : 'Arial,Helvetica,sans-serif' } );
			style.applyToRange( range );

			style = new CKEDITOR.style( styleDef, { 'family' : 'Comic Sans MS,cursive' } );
			style.applyToRange( range );

			style = new CKEDITOR.style( styleDef, { 'family' : 'Courier New,Courier,monospace' } );
			style.applyToRange( range );

			assert.areSame( '<span style="font-family:couriernew,courier,monospace;">outter</span><table><tbody><tr><td><span style="font-family:couriernew,courier,monospace;">text</span></td></tr></tbody></table><span style="font-family:couriernew,courier,monospace;">outter</span>', getInnerHtml( element ) );
		},

		test_ticket_3091_2 : function()
		{
			var element = doc.getById( '_P1' );
			element.setHtml( 'outter<p>text</p>outter' );

			var range = new CKEDITOR.dom.range( doc );
			range.selectNodeContents( element );

			var style = new CKEDITOR.style( { element : 'i', attributes : { title : 'x' } } );
			style.applyToRange( range );

			assert.areSame( '<i title="x">outter</i><p><i title="x">text</i></p><i title="x">outter</i>', getInnerHtml( element ), 'First step failed' );

			style = new CKEDITOR.style( { element : 'i', attributes : { title : 'y' } } );
			style.applyToRange( range );

			assert.areSame( '<i title="y">outter</i><p><i title="y">text</i></p><i title="y">outter</i>', getInnerHtml( element ), 'Second step failed' );

			style = new CKEDITOR.style( { element : 'i', attributes : { title : 'z' } } );
			style.applyToRange( range );

			assert.areSame( '<i title="z">outter</i><p><i title="z">text</i></p><i title="z">outter</i>', getInnerHtml( element ), 'Third step failed' );
		},

		// TC based on the state of the second step in the above test, before it got fixed.
		test_ticket_3091_3 : function()
		{
			var element = doc.getById( '_P1' );
			element.setHtml( '<p><i title="y">text</i><i title="x"></i></p><i title="y">outter</i><i title="x"></i>' );

			var range = new CKEDITOR.dom.range( doc );
			range.selectNodeContents( element );

			var style = new CKEDITOR.style( { element : 'i', attributes : { title : 'z' } } );
			style.applyToRange( range );

			assert.areSame( '<p><i title="z">text</i></p><i title="z">outter</i>', getInnerHtml( element ) );
		},

		// Remove inline style when range collapsed at element boundaries,
		// move out of the removing-style element, with inner style copied.
		test_ticket_3309 : function()
		{
			var element = doc.getById( '_P1' );
			element.setHtml( 'this is some <b><i id="_i1">styles</i></b> text' );

			// This is some <b><i>styles^</i></b> text
			var range = new CKEDITOR.dom.range( doc );
			range.setStartAt( doc.getById( '_i1' ), CKEDITOR.POSITION_BEFORE_END );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.removeFromRange( range );

			assert.areSame( 'this is some <b><i id="_i1">styles</i></b><i></i> text', getInnerHtml( element ) );
		},

		// No inner style preserved, simply move out of the removing-style element.
		test_ticket_3309_2 : function()
		{
			var element = doc.getById( '_P1' );
			element.setHtml( 'this is some <b id="_b1">styles</b> text' );

			// This is some <b>styles^</b> text
			var range = new CKEDITOR.dom.range( doc );
			range.setStartAt( doc.getById( '_b1' ), CKEDITOR.POSITION_BEFORE_END );

			var style = new CKEDITOR.style( { element : 'b' } );
			style.removeFromRange( range );
			// This is some <b>styles</b>^ text
			assert.areSame( doc.getById( '_b1' ).getParent().$, range.startContainer.$ );
			assert.areSame( 2, range.startOffset );
			assert.areSame( 'this is some <b id="_b1">styles</b> text', getInnerHtml( element ) );
		},

		// With style overrides.
		test_ticket_3309_3 : function()
		{
			var element = doc.getById( '_P1' );
			element.setHtml( 'text <strong><bold><span><b><i id="_i1">styles</i></b></span></bold></strong>' );

			// text <strong><bold><span><b><i id="_i1">^styles</i></b></span></bold></strong>
			var range = new CKEDITOR.dom.range( doc );
			range.setStartAt( doc.getById( '_i1' ), CKEDITOR.POSITION_AFTER_START );

			var style = new CKEDITOR.style( { element : 'b' , overrides : [ 'strong', 'bold' ] } );
			style.removeFromRange( range );

			// text <span><i>^</i></span><bold><span><b><i>styles</i></b></span></bold>
			assert.areSame( 'text <span><i></i></span><strong><bold><span><b><i id="_i1">styles</i></b></span></bold></strong>', getInnerHtml( element ) );
		},

		// Test convert multiple paragraphs to one <pre>.
		test_ticket_3188 : function()
		{
			var element = doc.getById( '_P1' );
			element.setHtml( '<p id="_P2">\nparagraph1<br /><br />para\t\ngraph2</p><p id="_P3">\nparagraph3\n</p>' );

			// <p id="_P2">[paragraph1</p><p id="_P3">paragraph2]</p>
			var range = new CKEDITOR.dom.range( doc );
			range.setStartAt( doc.getById( '_P2' ), CKEDITOR.POSITION_AFTER_START );
			range.setEndAt( doc.getById( '_P3' ), CKEDITOR.POSITION_BEFORE_END );

			var style = new CKEDITOR.style( { element : 'pre' } );
			style.applyToRange( range );

			var result = getInnerHtmlParsed( element );
			assert.areSame( '<pre>paragraph1\n\npara graph2\n\nparagraph3</pre>', result );
		},

		// Test convert one <pre> to multiple paragraphs.
		test_ticket_3188_2 : function()
		{
			var element = doc.getById( '_P1' );
			element.setHtml( '<pre>\n\tparagraph1\t\tparagraph1\nparagraph2\n\t\n\tpara   graph3\n</pre>' );

			//<pre>[\n\tparagraph1\t\tparagraph1\nparagraph2\n\t\n\tpara   graph3\n]</pre>
			var range = new CKEDITOR.dom.range( doc );
			range.selectNodeContents( doc.getById( '_P1' ).getFirst() );
			var style = new CKEDITOR.style( { element : 'p' } );
			style.applyToRange( range );

			var result = getInnerHtmlParsed( element );

			if ( CKEDITOR.env.webkit || CKEDITOR.env.opera )
				result = result.replace( /\xa0/g, '&nbsp;' );

			assert.areSame( '<p>&nbsp;paragraph1&nbsp; paragraph1<br />paragraph2</p><p>&nbsp;para&nbsp;&nbsp; graph3</p>',
					 result );
		},
		name : document.title
	};
})() );
//window.onload = testCase.test_ticket_3188;
	//]]>
	</script>
</head>
<body>
	<div id="_P1"></div>
</body>
</html>
